package main

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"errors"
	"fmt"
)

/**
des加密，分组cbc

des:
密钥：8bytes
分组长度：8bytes

cbc：


加密：



解密

*/
func main() {
	str := []byte("花落知多少,谁知天上宫阙，今夕是何年呀") //原始数据
	key := []byte("12345678")            //密钥
	mi_str, err := des_go_cbc(str, key)
	if err != nil {
		fmt.Println("加密失败.")
	}
	fmt.Println("2加密后数据为：", string(mi_str))

	jie_str, err := des_to_cbc(mi_str, key)
	if err != nil {
		fmt.Println("解密失败.")
	}
	fmt.Println("2解密后数据为：", string(jie_str))
}

func des_go_cbc(str []byte, key []byte) ([]byte, error) {
	// TODO func NewCipher(key []byte) (cipher.Block, error)
	fmt.Println("加密原数据：", str)
	block, err := des.NewCipher(key)
	if err != nil {
		fmt.Println("获取cipher.Block失败,", err)
		return nil, errors.New("获取cipher.Block失败")
	}
	// 数据填充
	str = add_info_strlen(str, block.BlockSize())
	//iv:=[]byte("12345678");
	fmt.Println("block.BlockSize=", block.BlockSize())
	iv := bytes.Repeat([]byte("1"), block.BlockSize())
	//使用cbc：func NewCBCEncrypter(b Block, iv []byte) BlockMode
	blockMode := cipher.NewCBCEncrypter(block, iv)
	//加密操作：
	blockMode.CryptBlocks(str, str)
	fmt.Println("1加密后数据为：", str)
	return str, nil
}

//             密文，密钥
func des_to_cbc(str []byte, key []byte) ([]byte, error) {
	// TODO func NewCipher(key []byte) (cipher.Block, error)
	block, err := des.NewCipher(key)
	if err != nil {
		fmt.Println("获取cipher.Block失败,", err)
		return nil, errors.New("获取cipher.Block失败")
	}
	// 解密
	iv := bytes.Repeat([]byte("1"), block.BlockSize())
	blockMode := cipher.NewCBCDecrypter(block, iv)
	//解密操作：
	blockMode.CryptBlocks(str, str)
	fmt.Println("1解密后数据为：", str)
	// 去除填充
	// TODO
	planstr := deele_info_strlen(str)
	return planstr, nil
}

/**
填充给不够的des 8位
*/
func add_info_strlen(str []byte, blockSize int) []byte {
	//.1计算传入原始数据的长度
	lenth := len(str)
	//.2需要填充的量
	add_number := blockSize - lenth%blockSize
	//.3把填充的长度转化为字符
	s1 := byte(add_number)
	//.4把字符拼接成数组
	s2 := bytes.Repeat([]byte{s1}, add_number)
	//.5拼接到后面
	srcnew := append(str, s2...)

	return srcnew
}

/**
删除多余的的des 8位
*/
func deele_info_strlen(str []byte) []byte {
	//.1计算传入原始数据的长度
	lenth := len(str)
	if lenth == 0 {
		panic("错误")
	}
	//.2获取最后一个字符
	last_byte := str[lenth-1]
	//.3把获取的最后一位转化为数字
	s1 := int(last_byte)
	//.4删除掉所有和s1数量与last_byte相同的
	str = str[:lenth-s1]

	return str
}
